home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / DocShell / RlShSync.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  11.1 KB  |  416 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        RlShSync.cpp
  3.  
  4.     Contains:    Document-synchronization stuff in the shell
  5.  
  6.     Owned by:    Jens Alfke
  7.     
  8.                 Portions by Mark Linton (see issue 23 of 'develop')
  9.  
  10.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.  
  14.          <6>     9/29/95    eeh        1287262: use ShellDef.h
  15.          <5>     9/12/95    JP        Check for null draft (build break)
  16.          <4>     9/11/95    JP        1269048 & 1283405: Cope with multiple
  17.                                     documents
  18.          <3>      9/5/95    TÇ        FBs: 1266428, 1274419, 1274421, 1274423,
  19.                                     1274429, 1274435 Fixed the Shell to handle
  20.                                     multiple documents in a process. Needed for
  21.                                     CyberDog.
  22.          <2>     8/15/95    TÇ        1261899 DocUtils getters should be renamed
  23.                                     Acquire___
  24.          <1>      8/8/95    jpa        first checked in
  25. */
  26.  
  27.  
  28. #ifndef _RLSHELL_
  29. #include "RlShell.h"
  30. #endif
  31.  
  32. #ifndef _SHELLDEF_
  33. #include "ShellDef.h"
  34. #endif
  35.  
  36. #ifndef SOM_ODDispatcher_xh
  37. #include <Disptch.xh>
  38. #endif
  39.  
  40. #ifndef SOM_ODWindowState_xh
  41. #include <WinStat.xh>
  42. #endif
  43.  
  44. #ifndef _DLOGUTIL_
  45. #include <DlogUtil.h>
  46. #endif
  47.  
  48. #ifndef _DOCUTILS_
  49. #include <DocUtils.h>
  50. #endif
  51.  
  52. #ifndef _INFOUTIL_
  53. #include <InfoUtil.h>
  54. #endif
  55.  
  56. #ifndef _PASCLSTR_
  57. #include <PasclStr.h>
  58. #endif
  59.  
  60. #ifndef _TEMPOBJ_
  61. #include <TempObj.h>
  62. #endif
  63.  
  64. #include <AppleEvents.h>
  65. #include <AERegistry.h>
  66. #include <Aliases.h>
  67. #include <Drag.h>
  68. #include <Folders.h>
  69. #include <Script.h>
  70.  
  71.  
  72. #undef ASK_SAVE_TO_TRASH    /* Define to ask user what to do when modified
  73.                                document is dragged to trash */
  74.  
  75.  
  76. //==============================================================================
  77. // Constants
  78. //==============================================================================
  79.  
  80. enum {                            // Buttons for kSHLDragToTrashAlert
  81.     kTrashSaveIndex = 1,
  82.     kTrashDontSaveIndex,
  83.     kTrashRetrieveIndex
  84. };
  85.  
  86. #ifndef kAEFinderSuite
  87. #define kAEFinderSuite 'fndr'
  88. #endif
  89.  
  90. #ifndef kAEPutAway
  91. #define kAEPutAway 'ptwy'
  92. #endif
  93.  
  94. const ODSShort kNumBetween = 20;
  95.  
  96.  
  97. //==============================================================================
  98. // Static Function Prototypes
  99. //==============================================================================
  100.  
  101. static void  ZoomWindowToTrash( WindowPtr );
  102. static OSErr SendFinderEvent(AEEventClass, AEEventID, const FSSpec& );
  103. static ODULong GetMostRecentVolModDate();
  104.  
  105.  
  106. //==============================================================================
  107. // Static Globals
  108. //==============================================================================
  109. static ODULong    lastChecked = 0;    // time of the last disk check
  110.  
  111. //==============================================================================
  112. // Shell Methods
  113. //==============================================================================
  114.  
  115. //-------------------------------------------------------------------------------------
  116. // RealShell::CheckFileLocation
  117. //-------------------------------------------------------------------------------------
  118.  
  119. ODBoolean
  120. RealShell::CheckFileLocation( )
  121. {
  122.     ODULong                n = 1;
  123.     ODULong                nowTime;
  124.     char                firstCStr[256], secondCStr[256];
  125.  
  126.     nowTime = GetMostRecentVolModDate();
  127.     if (nowTime == lastChecked)
  128.         return kODFalse;    // bail if we've already checked during this second
  129.     
  130.     ODDocument* document = ODGetNthOpenDocument(fEV, fSession, n);
  131.     RETURN_IF_NULL(document, kODFalse);
  132.  
  133.     while (document != kODNULL)
  134.     {
  135.         TempPlatformFile file = GetPlatformFileFromContainer(fEV, 
  136.                 document->GetContainer(fEV));
  137.         ODDraft* tempDraft = ODGetTempDraftFromOpenDocument(fEV, fSession, document);
  138.         if (tempDraft != kODNULL)
  139.         {
  140.             TempODPart root = ODAcquireRootPartOfDraft(fEV, tempDraft);
  141.             TempODName partName = ODGetPOName(fEV, root, kODNULL);
  142.             TempODName fileName = file->GetName();
  143.             
  144.             if(strcmp( GetITextString(partName, firstCStr),
  145.                     GetITextString(fileName, secondCStr) ) != 0)
  146.             {
  147.                 // Filename changed: rename root part
  148.                 
  149.                 ODSetPOName(fEV, root, fileName);
  150.                 ODRenamePartWindows(fEV, fSession, root, partName, fileName);
  151.             }
  152.         }
  153.         
  154.         if(file->IsInTrash() ) {
  155.             // File has been moved to trash: close document.
  156. #ifdef ASK_SAVE_TO_TRASH
  157.             if( this->HasWriteAccess() && tempDraft && tempDraft->ChangedFromPrev(fEV) )
  158.                 this->Notify(&RealShell::NotifyDragToTrash);
  159.             else
  160. #endif
  161.                 this->CloseTrashedDocument(document, kAEYes);
  162.             return fDispatcher->ShouldExit(fEV);
  163.         } else
  164.             // If it's no longer in the trash, don't bother to notify:
  165.             this->CancelNotification(&RealShell::NotifyDragToTrash);
  166.         document = ODGetNthOpenDocument(fEV, fSession, ++n);
  167.     }
  168.     lastChecked = nowTime;
  169.     return kODFalse;
  170. }
  171.  
  172.  
  173. //-------------------------------------------------------------------------------------
  174. // RealShell::NotifyDragToTrash
  175. //-------------------------------------------------------------------------------------
  176.  
  177. void
  178. RealShell::NotifyDragToTrash( ODULong /*refCon*/ )
  179. {
  180. #ifdef ASK_SAVE_TO_TRASH
  181.     char    fileName[256];
  182.     this->GetUserFileName(fileName, 255);
  183.     CToPascalString(fileName);
  184.     ParamText((ConstStr255Param)fileName, kODNULL,kODNULL,kODNULL);
  185.  
  186.     ODSShort result= ShowAlert(fEV,kSHLDragToTrashAlert,GetODDialogFilter(),fSession);
  187.     if( result == kTrashRetrieveIndex )
  188.         SendFinderEvent(kAEFinderSuite,kAEPutAway, fFile.GetFileSpec());
  189.     else
  190.         this->CloseTrashedDocument( result==kTrashSaveIndex ?kAEYes :kAENo);
  191. #endif
  192. }
  193.  
  194.  
  195. void
  196. RealShell::CloseTrashedDocument(ODDocument* document, DescType saveOptions )
  197. {
  198.     ODSaveDocument(fEV, fSession, document);
  199.     {
  200.         TempODWindow w = fWindowState->AcquireFrontRootWindow(fEV);
  201.         ZoomWindowToTrash(w->GetPlatformWindow(fEV));
  202.     }
  203.     if (ODCloseDocument(fEV, fSession, document))
  204.         fDispatcher->Exit(fEV);
  205. }
  206.  
  207.  
  208. //==============================================================================
  209. // Static Functions
  210. //==============================================================================
  211.  
  212.  
  213. //-------------------------------------------------------------------------------------
  214. // GetTrashIconRect
  215. //-------------------------------------------------------------------------------------
  216.  
  217. static OSErr
  218. GetTrashIconRect(Rect *aRect) {
  219.     OSErr theError;
  220.     short theVRefNum;
  221.     long theDirID;
  222.     Str255 theName;
  223.     CInfoPBRec pb;
  224.     Point thePoint;
  225.     
  226.     theError = FindFolder(kOnSystemDisk, kTrashFolderType, kDontCreateFolder,
  227.         &theVRefNum, &theDirID);
  228.     if (theError == fnfErr) {
  229.         theError = FindFolder(kOnSystemDisk, kWhereToEmptyTrashFolderType, kDontCreateFolder,
  230.             &theVRefNum, &theDirID);
  231.     }
  232.     if (theError == noErr) {
  233.         pb.dirInfo.ioNamePtr = theName;
  234.         pb.dirInfo.ioVRefNum = theVRefNum;
  235.         pb.dirInfo.ioDrDirID = theDirID;
  236.         pb.dirInfo.ioFDirIndex = -1;    /* use ioDrDirID */
  237.         theError = PBGetCatInfoSync(&pb);
  238.         if (theError == noErr) {
  239.             thePoint.v = pb.dirInfo.ioDrUsrWds.frLocation.v;
  240.             thePoint.h = pb.dirInfo.ioDrUsrWds.frLocation.h;
  241.             LocalToGlobal(&thePoint);
  242.             aRect->top = thePoint.v;
  243.             aRect->left = thePoint.h;
  244.             aRect->bottom = aRect->top + 32;
  245.             aRect->right = aRect->left + 32;
  246.         }
  247.     }
  248.     return theError;
  249. }
  250.  
  251.  
  252. //-------------------------------------------------------------------------------------
  253. // UpdateDesktop
  254. //-------------------------------------------------------------------------------------
  255.  
  256. static void
  257. UpdateDesktop( )
  258. {
  259.     EventRecord theEvent;
  260.     (void)WaitNextEvent(0, &theEvent, 10, kODNULL);
  261. }
  262.  
  263. //-------------------------------------------------------------------------------------
  264. // ZoomWindowToTrash
  265. //-------------------------------------------------------------------------------------
  266.  
  267. static void
  268. ZoomWindowToTrash( WindowPtr aWindow )
  269. {
  270.     GrafPtr curPort, wmgrPort;
  271.     GetPort(&curPort);
  272.  
  273.     Rect theStartingRect, theEndingRect;
  274.     theStartingRect = aWindow->portRect;
  275.     SetPort(aWindow);
  276.     LocalToGlobal((Point*)&theStartingRect.top);
  277.     LocalToGlobal((Point*)&theStartingRect.bottom);
  278.  
  279.     HideWindow(aWindow);
  280.     UpdateDesktop();
  281.     GetWMgrPort(&wmgrPort);
  282.     SetPort(wmgrPort);
  283.  
  284.     OSErr theError = GetTrashIconRect(&theEndingRect);
  285.     if( !theError )
  286.         ZoomRects(&theStartingRect,&theEndingRect,kNumBetween,zoomNoAcceleration);
  287.  
  288.     SetPort(curPort);
  289. }
  290.  
  291.  
  292. #ifdef ASK_SAVE_TO_TRASH
  293.  
  294. //-------------------------------------------------------------------------------------
  295. // FindFinder
  296. //-------------------------------------------------------------------------------------
  297.  
  298. #define kSystemType    'FNDR'
  299. #define kFinderSig    'MACS'
  300.  
  301. static OSErr
  302. FindFinder(ProcessSerialNumberPtr aPSN)
  303. {
  304.     ProcessInfoRec    theProcessInfo;
  305.     FSSpec            theProcessFile;
  306.     Str31            theProcessName;
  307.     OSErr            theError = noErr;
  308.  
  309.     aPSN->lowLongOfPSN = 0;
  310.     aPSN->highLongOfPSN = kNoProcess;
  311.     theProcessInfo.processInfoLength = sizeof(ProcessInfoRec);
  312.     theProcessInfo.processName = theProcessName;
  313.     theProcessInfo.processAppSpec = &theProcessFile;
  314.     do {
  315.         theError = GetNextProcess(aPSN);
  316.         if (theError == noErr) {
  317.             GetProcessInformation(aPSN, &theProcessInfo);
  318.         }
  319.     } while(((theProcessInfo.processSignature != kFinderSig) ||
  320.         (theProcessInfo.processType != kSystemType)) &&
  321.         (theError == noErr));
  322.     return(theError);
  323. }
  324.  
  325.  
  326. //-------------------------------------------------------------------------------------
  327. // SendFinderEvent
  328. //-------------------------------------------------------------------------------------
  329.  
  330. static OSErr
  331. SendFinderEvent(AEEventClass aClass, AEEventID anID, 
  332.                 const FSSpec &aFile)
  333. {
  334.     OSErr theError;
  335.     AppleEvent theAppleEvent, theReplyEvent;
  336.     AEDesc targetAddrDesc, theFileDesc;
  337.     AEDescList theFileDescList;
  338.     AliasHandle theFileAlias;
  339.     ProcessSerialNumber theFinder;
  340.     
  341.     theAppleEvent.dataHandle = nil;
  342.     theFileDescList.dataHandle = nil;
  343.     theFileDesc.dataHandle = nil;
  344.     theFileAlias = nil;
  345.     theError = FindFinder(&theFinder);
  346.     if (theError == noErr) {    
  347.         theError = AECreateDesc(typeProcessSerialNumber, 
  348.             (Ptr)&theFinder, sizeof(ProcessSerialNumber), 
  349.             &targetAddrDesc);
  350.     }
  351.     if (theError == noErr) {    
  352.         theError = AECreateList(nil, 0, false, &theFileDescList);
  353.     }
  354.     if (theError == noErr) {
  355.         theError = NewAlias(nil, &aFile, &theFileAlias);
  356.     }
  357.     if (theError == noErr) {
  358.         HLock((Handle) theFileAlias);
  359.         theError = AECreateDesc(typeAlias, (Ptr) *theFileAlias, 
  360.             GetHandleSize((Handle) theFileAlias), &theFileDesc);
  361.         HUnlock((Handle) theFileAlias);
  362.     }
  363.     if (theError == noErr) {
  364.         theError = AEPutDesc(&theFileDescList, 0, &theFileDesc);
  365.     }
  366.     if (theError == noErr) {
  367.         theError = AECreateAppleEvent(aClass, anID, 
  368.             &targetAddrDesc, kAutoGenerateReturnID, 
  369.             kAnyTransactionID, &theAppleEvent);
  370.     }
  371.     if (theError == noErr) {
  372.         theError = AEPutParamDesc(&theAppleEvent, keyDirectObject, 
  373.             &theFileDescList);
  374.     }
  375.     if (theError == noErr) {
  376.         theError = AESend(&theAppleEvent, &theReplyEvent, 
  377.             kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, 
  378.             kAENormalPriority, kAEDefaultTimeout, nil, nil);
  379.     }
  380.     if (theAppleEvent.dataHandle != nil) {
  381.         (void)AEDisposeDesc(&theAppleEvent);
  382.     }
  383.     if (theFileDescList.dataHandle != nil) {
  384.         (void)AEDisposeDesc(&theFileDescList);
  385.     }
  386.     if (theFileDesc.dataHandle != nil) {
  387.         (void)AEDisposeDesc(&theFileDesc);
  388.     }
  389.     if (theFileAlias != nil) {
  390.         DisposeHandle((Handle)theFileAlias);
  391.     }
  392.     return theError;
  393. }
  394.  
  395. #endif /*ASK_SAVE_TO_TRASH*/
  396.  
  397. ODULong
  398. GetMostRecentVolModDate()
  399. {
  400.     ODULong            bigModDate = 0;
  401.     OSErr            err = noErr;
  402.     ODSShort        index = 0;
  403.     HParamBlockRec    pb;
  404.     
  405.     pb.volumeParam.ioNamePtr = kODNULL; /* Don't care about name */
  406.     pb.volumeParam.ioVRefNum = 0;    /* Don't care about vRefNum */
  407.     while (err == noErr)
  408.     {
  409.         pb.volumeParam.ioVolIndex = ++index;
  410.         err = PBHGetVInfoSync(&pb);
  411.         if (err == noErr && pb.volumeParam.ioVLsMod > bigModDate)
  412.             bigModDate = pb.volumeParam.ioVLsMod;
  413.     }
  414.     return bigModDate;
  415. }
  416.